using System;
using System.Text;
using System.IO;


using gudusoft.gsqlparser;
using gudusoft.gsqlparser.Units;

namespace storedprocedureinfo
{
    class storedprocedureinfo
    {
        static void Main(string[] args)
        {
            string inputfile = "";
            string lcsqltext = "";

            if (args.Length == 0)
            {
                Console.WriteLine("storedprocedureinfo scriptfile");
                return;
            }

            inputfile = args[0];

            //Reading from file
            try
            {
                StreamReader re = File.OpenText(inputfile); //new StreamReader(inputfile,new UnicodeEncoding());//

                string input = null;
                while ((input = re.ReadLine()) != null)
                {
                    lcsqltext = lcsqltext + Environment.NewLine + input;
                }
            }
            catch (Exception e)
            {
                // Let the user know what went wrong.
                Console.WriteLine("File could not be read:");
                Console.WriteLine(e.Message);
                return;
            }

            TGSqlParser sqlparser = new TGSqlParser(TDbVendor.DbVMssql);
            sqlparser.SqlText.Text = lcsqltext;
            int i = sqlparser.Parse();

            if (i == 0)
            {
                foreach (TCustomSqlStatement stmt in sqlparser.SqlStatements)
                {
                    if (stmt.SqlStatementType == TSqlStatementType.sstMssqlCreateFunction)
                    {
                        analyzefunction((TMssqlCreateFunction)stmt);
                    }
                }

            }
            else
            {
                Console.WriteLine(sqlparser.ErrorMessages);
            }

        }

        public static void analyzefunction(TMssqlCreateFunction psql)
        {
            Console.WriteLine("Start to analyzing function...");
            Console.WriteLine("Function name: {0}", psql.functionname.AsText);
            if (psql.procedure_parameters_declaration != null)
            {
                Console.WriteLine("Parameters...");
                for (int i = 0; i < psql.procedure_parameters_declaration.Count(); i++)
                {
                    _TMssql_ParameterDecl p = (_TMssql_ParameterDecl)psql.procedure_parameters_declaration[i];
                    Console.WriteLine("\tParameter name: {0}, type: {1}",p._parameter_name.AsText,p._datatype.AsText);
                }
            }

            Console.WriteLine("Return type...");
            switch (psql.functiontype)
            {
                case TLzUDFType.uftScalar:
                    Console.WriteLine(psql.returntype.AsText);
                    if (psql.blockstmt != null)
                    {
                        foreach(TCustomSqlStatement stmt in psql.blockstmt.SqlStatements){

                            if (stmt.SqlStatementType == TSqlStatementType.sstSelect)
                            {
                                TSelectSqlStatement select = (TSelectSqlStatement)stmt;
                                Console.WriteLine("\tresult sets:");
                                foreach (TLzField field in select.Fields)
                                {
                                    Console.WriteLine("\t\t {0}", field.FieldName);
                                }
                            }

                            if (stmt.SqlStatementType == TSqlStatementType.sstMssqlReturn)
                            {
                                TMssqlReturn returnstmt = (TMssqlReturn)stmt;
                                Console.WriteLine("\tresult :");
                                if (returnstmt.expr != null)
                                {
                                    TLzCustomExpression lcexpr = (TLzCustomExpression)(returnstmt.expr);
                                    if (lcexpr.oper == TLzOpType.Expr_Parenthesis)
                                    {
                                        Console.WriteLine("\t\t {0}", lcexpr.lexpr.AsText);
                                    }
                                    else
                                    {
                                        Console.WriteLine("\t\t {0}", lcexpr.AsText);
                                    }
                                }
                            }
                        }
                    }
                    break;
                case TLzUDFType.uftInlineTableValued:
                    if (psql.returnstmt != null)
                    {
                        TLzCustomExpression lcexpr = (TLzCustomExpression)(psql.returnstmt.expr);

                        if ( lcexpr.oper == TLzOpType.Expr_subquery){
                            //return value is a subquery
                            TSelectSqlStatement select = (TSelectSqlStatement)lcexpr.lexpr;
                            Console.WriteLine("\tresult sets:");
                            foreach (TLzField field in select.Fields)
                            {
                               Console.WriteLine("\t\t {0}",field.FieldName);
                            }
                        }
                    }
                    break;
                case TLzUDFType.uftMultiStatementTableValued:
                    if (psql.blockstmt != null)
                    {
                        Console.WriteLine("Return table: {0}",psql.returnTableVar.AsText);
                        foreach (TLzField field in psql.Table.Fields)
                        {
                            Console.WriteLine("\t\t {0}", field.FieldName);
                        }

                        foreach (TCustomSqlStatement stmt in psql.blockstmt.SqlStatements)
                        {
                            //Console.WriteLine("sql type: {0}",stmt.SqlStatementType);
                            if (stmt.SqlStatementType == TSqlStatementType.sstSelect)
                            {
                                TSelectSqlStatement select = (TSelectSqlStatement)stmt;
                                Console.WriteLine("\tresult sets:");
                                if (select.SelectSetType == TSelectSetType.sltNone)
                                {
                                    foreach (TLzField field in select.Fields)
                                    {
                                        Console.WriteLine("\t\t {0}", field.FieldName);
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("\tresult sets:");
                                    TSelectSqlStatement selectleft = select.LeftStmt;
                                    if (selectleft.SelectSetType == TSelectSetType.sltNone)
                                    {
                                        foreach (TLzField field in selectleft.Fields)
                                        {
                                            Console.WriteLine("\t\t {0}", field.FieldName);
                                        }
                                    }

                                }
                            }

                            if (stmt.SqlStatementType == TSqlStatementType.sstMssqlReturn)
                            {
                                TMssqlReturn returnstmt = (TMssqlReturn)stmt;
                                Console.WriteLine("\tresult :");
                                if (returnstmt.expr != null)
                                {
                                    TLzCustomExpression lcexpr = (TLzCustomExpression)(returnstmt.expr);
                                    if (lcexpr.oper == TLzOpType.Expr_Parenthesis)
                                    {
                                        Console.WriteLine("\t\t {0}", lcexpr.lexpr.AsText);
                                    }
                                    else
                                    {
                                        Console.WriteLine("\t\t {0}", lcexpr.AsText);
                                    }
                                }
                            }

                        }
                    }
                    break;
            }
            
            Console.WriteLine("");
        }

    }
}
